package app

import (
	"fmt"
	"openzbox.com/driver/conn/serial"
	"openzbox.com/protocol/modbus"
	"time"
)

//https://blog.csdn.net/u011041241/article/details/109240555
//https://modbus.org/specs.php
//https://blog.csdn.net/sym_robot/article/details/112967586?spm=1001.2101.3001.6650.17&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-17-112967586-blog-118347661.pc_relevant_3mothn_strategy_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-17-112967586-blog-118347661.pc_relevant_3mothn_strategy_recovery&utm_relevant_index=24
//https://zhuanlan.zhihu.com/p/146486090
//https://blog.csdn.net/tiandiren111/article/details/118347661
//https://www.cnblogs.com/iluzhiyong/p/4301192.html
/*
主机发送: 01 03 00 00 00 01 84 0A
从机回复: 01 03 02 19 98 B2 7E
*/
/*
1.概念
①Coil和Register
　　Modbus中定义的两种数据类型。Coil是位（bit）变量；Register是整型（Word，即16-bit）变量。
②Slave和Master与Server和Client
　　同一种设备在不同领域的不同叫法。
　　Slave： 工业自动化用语；响应请求；
　　Master：工业自动化用语；发送请求；
　　Server：IT用语；响应请求；
　　Client：IT用语；发送请求；
　　在Modbus中，Slave和Server意思相同，Master和Client意思相同。

2.Modbus数据模型
　　Modbus中，数据可以分为两大类，分别为Coil和Register，每一种数据，根据读写方式的不同，又可细分为两种（只读，读写）。
　　Modbus四种数据类型：
　　Discretes Input　　　　位变量　　　　只读
　　Coils　　　　　　　　　 位变量　　　　读写
　　Input Registers　　　　16-bit整型 　 只读
　　Holding Registers 　　  16-bit整型 　 读写
　　通常，在Slave端中，定义四张表来实现四种数据。


3.Modbus地址范围对应表

设备地址 　　　　Modbus地址　　    描述 　　                功能 　　R/W
1~10000 　　    address-1           Coils（Output）       0          R/W
10001~20000   address-10001    Discrete Inputs        01        R
30001~40000   address-30001    Input Registers        04        R
40001~50000   address-40001    Holding Registers     03        R/W

4.Modbus变量地址
映射地址             Function Code         地址类型          R/W          描述
0xxxx               01,05,15                 Coil                R/W          -
1xxxx               02                          离散输入          R              -
2xxxx               03,04,06,16            浮点寄存器       R/W          两个连续16-bit寄存器表示一个浮点数（IEEE754）
3xxxx               04                          输入寄存器       R              每个寄存器表示一个16-bit无符号整数（0~65535）
4xxxx               03,06,16                保持寄存器        R/W          -
5xxxx               03,04,06,16           ASCII字符         R/W          每个寄存器表示两个ASCII字符
*/

func StartCom1ModbusRTU() {
	//glog.Base().SetLevel("debug")
	p := modbus.NewRTUClientProvider(modbus.WithEnableLogger(),
		modbus.WithSerialConfig(serial.Config{
			Address:  "/dev/ttyS8",
			BaudRate: 115200,
			DataBits: 8,
			StopBits: 1,
			Parity:   "N",
			Timeout:  modbus.SerialDefaultTimeout,
		}, /*serial.OpenOptions{
			PortName:             "/dev/ttyS7", //  (args[0]).(string),
			BaudRate:             115200,
			DataBits:             8,
			StopBits:             1,
			ParityMode:           0,
			MinimumReadSize:      1,
			Rs485Enable:          true,
			Rs485ResponseTimeout: 1000,
		}*/))

	client := modbus.NewClient(p)
	err := client.Connect()
	if err != nil {
		fmt.Println("connect failed, ", err)
		return
	}
	defer client.Close()

	for {
		//_, err := client.ReadHoldingRegisters(1, 0x00, 10)
		rtx, err := client.ReadCoils(1, 0x00, 8)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println(rtx)

		//	fmt.Printf("ReadDiscreteInputs %#v\r\n", results)
		time.Sleep(time.Second * 2)
		//fmt.Printf("%2x \r\n", result)
	}
}
func StartCom2ModbusRTU() {
	//glog.Base().SetLevel("debug")
	p := modbus.NewRTUClientProvider(modbus.WithEnableLogger(),
		modbus.WithSerialConfig(serial.Config{
			Address:  "/dev/ttyS3",
			BaudRate: 115200,
			DataBits: 8,
			StopBits: 1,
			Parity:   "N",
			Timeout:  modbus.SerialDefaultTimeout,
		}, /*serial.OpenOptions{
			PortName:             "/dev/ttyS7", //  (args[0]).(string),
			BaudRate:             115200,
			DataBits:             8,
			StopBits:             1,
			ParityMode:           0,
			MinimumReadSize:      1,
			Rs485Enable:          true,
			Rs485ResponseTimeout: 1000,
		}*/))

	client := modbus.NewClient(p)
	err := client.Connect()
	if err != nil {
		fmt.Println("connect failed, ", err)
		return
	}
	defer client.Close()

	for {
		//_, err := client.ReadHoldingRegisters(1, 0x00, 10)
		rtx, err := client.ReadCoils(2, 0x00, 8)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println(rtx)

		//	fmt.Printf("ReadDiscreteInputs %#v\r\n", results)
		time.Sleep(time.Second * 2)
		//fmt.Printf("%2x \r\n", result)
	}
}
func StartCom3ModbusRTU() {
	//glog.Base().SetLevel("debug")
	p := modbus.NewRTUClientProvider(modbus.WithEnableLogger(),
		modbus.WithSerialConfig(serial.Config{
			Address:  "/dev/ttyS7",
			BaudRate: 115200,
			DataBits: 8,
			StopBits: 1,
			Parity:   "N",
			Timeout:  modbus.SerialDefaultTimeout,
		}, /*serial.OpenOptions{
			PortName:             "/dev/ttyS7", //  (args[0]).(string),
			BaudRate:             115200,
			DataBits:             8,
			StopBits:             1,
			ParityMode:           0,
			MinimumReadSize:      1,
			Rs485Enable:          true,
			Rs485ResponseTimeout: 1000,
		}*/))

	client := modbus.NewClient(p)
	err := client.Connect()
	if err != nil {
		fmt.Println("connect failed, ", err)
		return
	}
	defer client.Close()

	for {
		//_, err := client.ReadHoldingRegisters(1, 0x00, 10)
		rtx, err := client.ReadCoils(3, 0x00, 8)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println(rtx)

		//	fmt.Printf("ReadDiscreteInputs %#v\r\n", results)
		time.Sleep(time.Second * 2)
		//fmt.Printf("%2x \r\n", result)
	}
}
func StartCom4ModbusRTU() {
	//glog.Base().SetLevel("debug")
	p := modbus.NewRTUClientProvider(modbus.WithEnableLogger(),
		modbus.WithSerialConfig(serial.Config{
			Address:  "/dev/ttyS6",
			BaudRate: 115200,
			DataBits: 8,
			StopBits: 1,
			Parity:   "N",
			Timeout:  modbus.SerialDefaultTimeout,
		}, /*serial.OpenOptions{
			PortName:             "/dev/ttyS7", //  (args[0]).(string),
			BaudRate:             115200,
			DataBits:             8,
			StopBits:             1,
			ParityMode:           0,
			MinimumReadSize:      1,
			Rs485Enable:          true,
			Rs485ResponseTimeout: 1000,
		}*/))

	client := modbus.NewClient(p)
	err := client.Connect()
	if err != nil {
		fmt.Println("connect failed, ", err)
		return
	}
	defer client.Close()

	for {
		//_, err := client.ReadHoldingRegisters(1, 0x00, 10)
		rtx, err := client.ReadCoils(4, 0x00, 8)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println(rtx)

		//	fmt.Printf("ReadDiscreteInputs %#v\r\n", results)
		time.Sleep(time.Second * 2)
		//fmt.Printf("%2x \r\n", result)
	}
}
func StartCom5ModbusRTU() {
	//glog.Base().SetLevel("debug")
	p := modbus.NewRTUClientProvider(modbus.WithEnableLogger(),
		modbus.WithSerialConfig(serial.Config{
			Address:  "/dev/ttyS4",
			BaudRate: 115200,
			DataBits: 8,
			StopBits: 1,
			Parity:   "N",
			Timeout:  modbus.SerialDefaultTimeout,
		}, /*serial.OpenOptions{
			PortName:             "/dev/ttyS7", //  (args[0]).(string),
			BaudRate:             115200,
			DataBits:             8,
			StopBits:             1,
			ParityMode:           0,
			MinimumReadSize:      1,
			Rs485Enable:          true,
			Rs485ResponseTimeout: 1000,
		}*/))

	client := modbus.NewClient(p)
	err := client.Connect()
	if err != nil {
		fmt.Println("connect failed, ", err)
		return
	}
	defer client.Close()

	for {
		//_, err := client.ReadHoldingRegisters(1, 0x00, 10)
		rtx, err := client.ReadCoils(5, 0x00, 8)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println(rtx)

		//	fmt.Printf("ReadDiscreteInputs %#v\r\n", results)
		time.Sleep(time.Second * 2)
		//fmt.Printf("%2x \r\n", result)
	}
}
func StartCom6ModbusRTU() {
	//glog.Base().SetLevel("debug")
	p := modbus.NewRTUClientProvider(modbus.WithEnableLogger(),
		modbus.WithSerialConfig(serial.Config{
			Address:  "/dev/ttyS5",
			BaudRate: 115200,
			DataBits: 8,
			StopBits: 1,
			Parity:   "N",
			Timeout:  modbus.SerialDefaultTimeout,
		}, /*serial.OpenOptions{
			PortName:             "/dev/ttyS7", //  (args[0]).(string),
			BaudRate:             115200,
			DataBits:             8,
			StopBits:             1,
			ParityMode:           0,
			MinimumReadSize:      1,
			Rs485Enable:          true,
			Rs485ResponseTimeout: 1000,
		}*/))

	client := modbus.NewClient(p)
	err := client.Connect()
	if err != nil {
		fmt.Println("connect failed, ", err)
		return
	}
	defer client.Close()

	for {
		//_, err := client.ReadHoldingRegisters(1, 0x00, 10)
		rtx, err := client.ReadCoils(6, 0x00, 8)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println(rtx)

		//	fmt.Printf("ReadDiscreteInputs %#v\r\n", results)
		time.Sleep(time.Second * 2)
		//fmt.Printf("%2x \r\n", result)
	}
}
